home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / The Hacks / PhaseShiftX / Source / Shared / MachOUtils.cp < prev    next >
Encoding:
Text File  |  2001-06-23  |  5.4 KB  |  240 lines

  1. #ifdef __cplusplus
  2. extern "C" {
  3. #endif
  4.  
  5. #include <ctype.h>
  6. #include <fcntl.h>
  7. #include <mach/machine.h>
  8. #include <mach-o/dyld.h>
  9. #include <mach-o/fat.h>
  10. #include <mach-o/loader.h>
  11. #include <mach-o/nlist.h>
  12. #include <mach-o/stab.h>
  13. #include <stdio.h>
  14. #include <sys/mman.h>
  15. #include <sys/stat.h>
  16. #include <unistd.h>
  17.  
  18. #ifdef __cplusplus
  19. }
  20. #endif
  21.  
  22. #include "MachOUtils.h"
  23.  
  24.  
  25.  
  26. #ifdef __cplusplus
  27. extern "C" {
  28. #endif
  29.  
  30. struct mach_header *OpenImageFile(char *path,int *fd,struct stat *finfo,void **base);
  31. void CloseImageFile(int *fd,struct stat *finfo,void **base);
  32. UInt32 *FindSymbolAddressFromImage(struct mach_header *image,char *symbol);
  33. void *FindSectionAddressFromImage(struct mach_header *image,char *segment,char *section);
  34.  
  35. #ifdef __cplusplus
  36. }
  37. #endif
  38.  
  39.  
  40.  
  41. void *FindSymbolAddress(char *path,char *symbol)
  42. {
  43.     int                        fd;
  44.     struct stat                finfo;
  45.     void                    *base,*addr = NULL;
  46.     struct mach_header        *image;
  47.     
  48.     image = OpenImageFile(path,&fd,&finfo,&base);
  49.     if (image != NULL)
  50.     {
  51.         addr = FindSymbolAddressFromImage(image,symbol);
  52.         CloseImageFile(&fd,&finfo,&base);
  53.     }
  54.     
  55.     return addr;
  56. }
  57.  
  58.  
  59.  
  60. void *FindSectionAddress(char *path,char *segment,char *section)
  61. {
  62.     int                        fd;
  63.     struct stat                finfo;
  64.     void                    *base,*addr = NULL;
  65.     struct mach_header        *image;
  66.     
  67.     image = OpenImageFile(path,&fd,&finfo,&base);
  68.     if (image != NULL)
  69.     {
  70.         addr = FindSectionAddressFromImage(image,segment,section);
  71.         CloseImageFile(&fd,&finfo,&base);
  72.     }
  73.     
  74.     return addr;
  75. }
  76.  
  77.  
  78. #if 0
  79. #pragma mark -
  80. #endif
  81.  
  82.  
  83. struct mach_header *OpenImageFile(char *path,int *fd,struct stat *finfo,void **base)
  84. {
  85.     struct fat_header        *fathead;
  86.     struct fat_arch            *fatarch;
  87.     UInt32                    index;
  88.     
  89.     *fd = 0;
  90.     *base = NULL;
  91.     
  92.     *fd = open(path,0,O_RDONLY);
  93.     if (*fd > 0)
  94.     {
  95.         fstat(*fd,finfo);
  96.         *base = mmap(0,finfo->st_size,PROT_READ,MAP_FILE,*fd,0);
  97.         if (*base != (void*)-1)
  98.         {
  99.             fathead = (struct fat_header*)*base;
  100.             if (fathead->magic == FAT_MAGIC)
  101.             {
  102.                 fatarch = (struct fat_arch*)(((char*)*base) + sizeof(struct fat_header));
  103.                 for (index = 0;index < fathead->nfat_arch;index += 1)
  104.                     if (fatarch[index].cputype == CPU_TYPE_POWERPC)
  105.                         return (struct mach_header*)(((char*)*base) + fatarch[index].offset);
  106.             }
  107.             else
  108.                 return (struct mach_header*)*base;
  109.         }
  110.     }
  111.     
  112.     CloseImageFile(fd,finfo,base);
  113.     return NULL;
  114. }
  115.  
  116.  
  117.  
  118. void CloseImageFile(int *fd,struct stat *finfo,void **base)
  119. {
  120.     if (*fd > 0)
  121.     {
  122.         if (*base != NULL)
  123.         {
  124.             munmap(*base,finfo->st_size);
  125.             *base = NULL;
  126.         }
  127.         
  128.         close(*fd);
  129.         *fd = 0;
  130.     }
  131. }
  132.  
  133.  
  134.  
  135. UInt32 *FindSymbolAddressFromImage(struct mach_header *image,char *symbol)
  136. {
  137.     struct dysymtab_command    *dysymtab;
  138.     struct symtab_command    *symtab;
  139.     struct segment_command    *segCmd;
  140.     struct load_command        *loadCmd;
  141.     struct section            *sect;
  142.     struct nlist            *sym,*symbase = NULL;
  143.     char                    *str,*strings = NULL;
  144.     UInt32                    *indirectsyms,inbase = 0xFFFFFFFF;
  145.     UInt32                    lcdex,symdex,sectdex;
  146.     UInt8                    *inaddr = NULL;
  147.     
  148.     loadCmd = (struct load_command*)((char*)image + sizeof(struct mach_header));
  149.     for (lcdex = 0;lcdex < image->ncmds;lcdex += 1,loadCmd = (struct load_command*)((char*)loadCmd + loadCmd->cmdsize))
  150.     {
  151.         if (loadCmd->cmd == LC_SEGMENT)
  152.         {
  153.             segCmd = (struct segment_command*)loadCmd;
  154.             if (!strcmp("__DATA",segCmd->segname))
  155.             {
  156.                 sect = (struct section*)((char*)segCmd + sizeof(struct segment_command));
  157.                 for (sectdex = 0;sectdex < segCmd->nsects;sectdex += 1,sect += 1)
  158.                 {
  159.                     if (!strcmp("__la_symbol_ptr",sect->sectname))
  160.                     {
  161.                         inaddr = (UInt8*)sect->addr;
  162.                         inbase = sect->reserved1;
  163.                         break;
  164.                     }
  165.                 }
  166.             }
  167.         }
  168.     }
  169.     
  170.     if ((inaddr == NULL) || (inbase == 0xFFFFFFFF))
  171.         return NULL;
  172.     
  173.     loadCmd = (struct load_command*)((char*)image + sizeof(struct mach_header));
  174.     for (lcdex = 0;lcdex < image->ncmds;lcdex += 1,loadCmd = (struct load_command*)((char*)loadCmd + loadCmd->cmdsize))
  175.     {
  176.         if (loadCmd->cmd == LC_SYMTAB)
  177.         {
  178.             symtab = (struct symtab_command*)loadCmd;
  179.             symbase = (struct nlist*)((char*)image + symtab->symoff);
  180.             strings = (char*)image + symtab->stroff;
  181.             break;
  182.         }
  183.     }
  184.     
  185.     if ((symbase == NULL) || (strings == NULL))
  186.         return NULL;
  187.     
  188.     loadCmd = (struct load_command*)((char*)image + sizeof(struct mach_header));
  189.     for (lcdex = 0;lcdex < image->ncmds;lcdex += 1,loadCmd = (struct load_command*)((char*)loadCmd + loadCmd->cmdsize))
  190.     {
  191.         if (loadCmd->cmd == LC_DYSYMTAB)
  192.         {
  193.             dysymtab = (struct dysymtab_command*)loadCmd;
  194.             indirectsyms = (UInt32*)((char*)image + dysymtab->indirectsymoff);
  195.             
  196.             for (symdex = inbase;symdex < dysymtab->nindirectsyms;symdex += 1)
  197.             {
  198.                 sym = &symbase[indirectsyms[symdex]];
  199.                 str = (sym->n_un.n_strx != 0) ? (strings + sym->n_un.n_strx) : (char*)"";
  200.                 if (!strcmp(symbol,str))
  201.                 {
  202.                     return (UInt32*)(inaddr + ((symdex - inbase) * 4));
  203.                 }
  204.             }
  205.             
  206.             break;
  207.         }
  208.     }
  209.     
  210.     return NULL;
  211. }
  212.  
  213.  
  214.  
  215. void *FindSectionAddressFromImage(struct mach_header *image,char *segment,char *section)
  216. {
  217.     struct segment_command    *segCmd;
  218.     struct load_command        *loadCmd;
  219.     struct section            *sect;
  220.     UInt32                    lcdex,sectdex;
  221.     
  222.     loadCmd = (struct load_command*)((char*)image + sizeof(struct mach_header));
  223.     for (lcdex = 0;lcdex < image->ncmds;lcdex += 1,loadCmd = (struct load_command*)((char*)loadCmd + loadCmd->cmdsize))
  224.     {
  225.         if (loadCmd->cmd == LC_SEGMENT)
  226.         {
  227.             segCmd = (struct segment_command*)loadCmd;
  228.             if (!strcmp(segment,segCmd->segname))
  229.             {
  230.                 sect = (struct section*)((char*)segCmd + sizeof(struct segment_command));
  231.                 for (sectdex = 0;sectdex < segCmd->nsects;sectdex += 1,sect += 1)
  232.                     if (!strcmp(section,sect->sectname))
  233.                         return (void*)sect->addr;
  234.             }
  235.         }
  236.     }
  237.     
  238.     return NULL;
  239. }
  240.